package org.xiaozhou.chatgptcativen.interfaces;

import cn.bugstack.chatglm.model.*;
import cn.bugstack.chatglm.session.Configuration;
import cn.bugstack.chatglm.session.OpenAiSession;
import cn.bugstack.chatglm.session.defaults.DefaultOpenAiSessionFactory;
import okhttp3.logging.HttpLoggingInterceptor;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.bind.annotation.*;
import org.xiaozhou.chatgptcativen.application.IWeiXinValidateService;
import org.xiaozhou.chatgptcativen.domain.security.model.vo.MessageTextEntity;
import org.xiaozhou.chatgptcativen.infrastrctrue.utils.XmlUtil;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;

@RestController
@RequestMapping("/wx/portal/{appid}")
public class WeiXinPortalController {

    private Logger logger = org.slf4j.LoggerFactory.getLogger(WeiXinPortalController.class);

    @Value("${wx.config.originId}")
    private String originId;

    @Resource
    private IWeiXinValidateService weiXinValidateService;

    private final OpenAiSession openAiSession;


    //返回的数据
    private Map<String,String> openAiDataMap = new HashMap<>();

    //数据次数
    private Map<String,Integer> openAiRetryCountMap = new HashMap<>();

    private final  CountDownLatch latch = new CountDownLatch(2);

    //线程池处理任务
    @Resource
    private ThreadPoolTaskExecutor taskExecutor;

    public WeiXinPortalController(){
        Configuration configuration = new Configuration();
        configuration.setApiHost("https://open.bigmodel.cn/");
        configuration.setApiSecretKey("764d6c3f7231f0dcfb2daba77215f112.n23GxnTrlVlKBDvH");
        configuration.setLevel(HttpLoggingInterceptor.Level.BODY);
        //会话工厂
        DefaultOpenAiSessionFactory factory = new DefaultOpenAiSessionFactory(configuration);
        this.openAiSession=factory.openSession();
    }

    //微信公众号签名验证
    @GetMapping(produces = "text/plain;charset=utf-8")
    public String signal(@RequestParam(value = "signature",required = false)String signature,
                         @RequestParam(value = "timestamp",required = false)String timestamp,
                         @RequestParam(value = "nonce",required = false)String nonce,
                         @RequestParam(value = "echostr",required = false)String echostr){
        logger.info("微信请求参数：signature={},timestamp={},nonce={},echostr={}",signature,timestamp,nonce,echostr);
        try {
            if (StringUtils.isAnyBlank(signature,timestamp,nonce,echostr)){
                throw  new IllegalArgumentException("参数有无");
            }
            if (!weiXinValidateService.checkSign(signature,timestamp,nonce,echostr)){
                throw new RuntimeException("微信验签失败");
            }
            return echostr;
        }catch (Exception e){
            return null;
        }
    }
    /**
     * 此处是处理微信服务器的消息转发的
     */
    @PostMapping(produces = "application/xml; charset=UTF-8")
    public String post(@PathVariable String appid,
                       @RequestBody String requestBody,
                       @RequestParam("signature") String signature,
                       @RequestParam("timestamp") String timestamp,
                       @RequestParam("nonce") String nonce,
                       @RequestParam("openid") String openid,
                       @RequestParam(name = "encrypt_type", required = false) String encType,
                       @RequestParam(name = "msg_signature", required = false) String msgSignature) {
        try {
            logger.info("接收微信公众号信息请求{}开始 {}", openid, requestBody);
            MessageTextEntity message = XmlUtil.xmlToBean(requestBody, MessageTextEntity.class);
            logger.info("请求次数：{}", null == openAiRetryCountMap.get(message.getContent().trim()) ? 1 : openAiRetryCountMap.get(message.getContent().trim()));
            if (openAiDataMap.get(message.getContent().trim())==null || openAiDataMap.get(message.getContent().trim()) == "NULL"){
                // 记录次数
                if (openAiRetryCountMap.get(message.getContent().trim()) == null || openAiRetryCountMap.get(message.getContent().trim()) == 0){
                    doAITask(message.getContent().trim());
                    openAiRetryCountMap.put(message.getContent().trim(),1);
                    logger.info("进行第1次的问答尝试");
                    Thread.sleep(5000);
                    latch.await();
                    if (openAiDataMap.get(message.getContent().trim())!=null && openAiDataMap.get(message.getContent().trim()) != "NULL"){
                        logger.info("进行第1次的问答尝试成功");
                        latch.countDown();
                    }
                }else if (openAiRetryCountMap.get(message.getContent().trim()) <2){
                    Integer retryCount = openAiRetryCountMap.get(message.getContent().trim());
                    retryCount = retryCount + 1;
                    openAiRetryCountMap.put(message.getContent().trim(),retryCount);
                    logger.info("进行第{}次的问答尝试",retryCount);
                    Thread.sleep(1000);
                    latch.await();
                    if (openAiDataMap.get(message.getContent().trim())!=null && openAiDataMap.get(message.getContent().trim()) != "NULL"){
                        logger.info("进行第{}次的问答尝试成功",retryCount);
                        latch.countDown();
                    }
                }else {
                    Integer retryCount = openAiRetryCountMap.get(message.getContent().trim());
                    retryCount = retryCount + 1;
                    logger.info("进行第{}次的问答尝试",retryCount);
                    openAiRetryCountMap.put(message.getContent().trim(),retryCount);
                    if (openAiDataMap.get(message.getContent().trim())==null || openAiDataMap.get(message.getContent().trim()) == "NULL"){
                        //进行友好提示信息了
                        openAiDataMap.put(message.getContent().trim(),"请再次询问这个问题"+"【"+message.getContent().trim()+"】");
                    }
                }
            }

            // 反馈信息[文本]
            MessageTextEntity res = new MessageTextEntity();
            res.setToUserName(openid);
            res.setFromUserName(originId);
            res.setCreateTime(String.valueOf(System.currentTimeMillis() / 1000L));
            res.setMsgType("text");
            res.setContent(openAiDataMap.get(message.getContent().trim()));
            String result = XmlUtil.beanToXml(res);
            logger.info("接收微信公众号信息请求{}完成 {}", openid, result);
            openAiDataMap.remove(message.getContent().trim());
            return result;
        } catch (Exception e) {
            logger.error("接收微信公众号信息请求{}失败 {}", openid, requestBody, e);
            return "";
        }
    }


    private void doAITask(String question){
        openAiDataMap.put(question,"NULL");
        taskExecutor.execute(() -> {
            try {
                if (question.startsWith("画")){
                    // 2.1 提供的官网方法
                    ImageCompletionRequest newRequest = new ImageCompletionRequest();
                    newRequest.setModel(Model.COGVIEW_3);
                    newRequest.setPrompt(question);
                    ImageCompletionResponse imgResponse = openAiSession.genImages(newRequest);
                    // 保存数据
                    openAiDataMap.put(question, imgResponse.getData().get(0).getUrl());
                }else{
                    // 入参；模型、请求信息；记得更新最新版 ChatGLM-SDK-Java
                    ChatCompletionRequest request = new ChatCompletionRequest();
                    request.setModel(Model.GLM_3_5_TURBO); // chatGLM_6b_SSE、chatglm_lite、chatglm_lite_32k、chatglm_std、chatglm_pro
                    request.setPrompt(new ArrayList<ChatCompletionRequest.Prompt>() {
                        private static final long serialVersionUID = -7988151926241837899L;

                        {
                            add(ChatCompletionRequest.Prompt.builder()
                                    .role(Role.user.getCode())
                                    .content(question)
                                    .build());
                        }
                    });
                    // 2.1 提供的官网方法
                    ChatCompletionSyncResponse response = openAiSession.completionsSync(request);
                    // 保存数据
                    openAiDataMap.put(question, response.getChoices().get(0).getMessage().getContent());
                }
            }catch (Exception e){
                logger.info("{}：问题AI大模型回答失败", question);
            }
        });
    }


}
